package wili.insertCode;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;

import wili.c.Ca;
import wili.c.File9a;

/**
 * @author weila 2022年6月23日
 */
public abstract class InsertCode0 {
	static interface Action {
		String cost = "cost";
	}

	public InsertCode0() {
	}

	abstract boolean updateMethodPart(MethodPart part, String action);

	public void start_find_and_insert(Predicate<File> fileCond, BiFunction<File, String, String> methodCond) {
		Ca.SKipFields = true;
		JfilePart.allNum = 0;
		try {
			for (int i = 0; i < Coms2.srcRoots.length; i++) {
				File root = Coms2.srcRoots[i];
				try {
					this.traverseFile_and_doMethodPart(root, root, fileCond, methodCond);
				} catch (Exception e) {
					System.err.println(i + ", insertCode:" + e);
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			Coms2.log(" allNum=" + JfilePart.allNum + ", patchedNum=" + JfilePart.patchedNum);
		}
	}

	private void traverseFile_and_doMethodPart(File root, File file, Predicate<File> fileCond,
			BiFunction<File, String, String> methodCond) {
		/*
		
		 */
		if (!file.exists()) {
			Coms2.asert(false, "FileNotFound:" + file.getAbsolutePath());
		}
		//Coms.log("InsertCode0:" + root.getAbsolutePath());

		if (file.isDirectory()) {
			for (File ff : file.listFiles()) {
				traverseFile_and_doMethodPart(root, ff, fileCond, methodCond);
			}
		} else if (file.getName().endsWith(".java")) {
			if (!fileCond.test(file))
				return;
			JfilePart fi = JfilePart.newInst(root, file);
			if (fi == null)
				return;//may already patched.
			int times = 0;
			for (ClassPart cp : fi.clsParts) {
				for (MethodPart mp : cp.methodMap.values()) {
					String action = methodCond.apply(file, mp.name);
					if (action != null) {
						if (this.updateMethodPart(mp, action))
							++times;
					}
				}
			}
			if (times == 0)
				return;
			fi.saveFile();
		}
	}

	public void insertMethod(List<JfilePart> ff) {
		for (JfilePart file : ff) {
			file.findMethod();
		}
	}

	static void findRourceDirs() {
		int opt = 1;
		if (opt == 1) {//b1 client.
			int[] dirNum = { 0 };
			List<File> dirList = new ArrayList<>();
			//C:\Perforce\b1a\BUSMB_B1\SBO\dev\Source\WebClient\java\tcli
			File rootBase = new File("C:\\Perforce\\b1a\\BUSMB_B1\\SBO\\dev\\Source\\WebClient\\java");
			rootBase = new File(rootBase, "tcli");
			File9a.findFiles(rootBase, dirList, new Function<File, File[]>() {
				@Override
				public File[] apply(File fil) {
					if (fil.isDirectory()) {
						if (fil.getName().startsWith(".")) {
							return new File[] {};
						} else if (fil.getName().equals("src")) {
							File file = new File(fil, "main");
							if (file.exists() && file.isDirectory()) {
								File file2 = new File(file, "java");
								if (file2.exists() && file2.isDirectory()) {
									++dirNum[0];
									// Coms9.log("\"" + file2 + "\"");
									return new File[] { file2 };
								}
							}
						}
					}
					return null;
				}
			});
			Coms2.log(" dirNum=" + dirNum[0]);
			Collections.sort(dirList);
			Coms2.log(dirList);
		} else {
			List<File> toList = new ArrayList<>();
			File9a.findFiles(new File("D:\\bearJ\\autoeq2"), toList, new Function<File, File[]>() {
				@Override
				public File[] apply(File t) {
					if (t.isDirectory() && t.getName().equals("src")) {
						File file = new File(t, "main");
						if (file.exists() && file.isDirectory()) {
							file = new File(t, "java");
							if (file.exists() && file.isDirectory()) {
								return new File[] { file };
							}
						}
					}
					return null;
				}
			});
		}
	}
}
